#include "include.h"
#include "bsp_dac.h"

typedef struct {
	u8 eq_en;
	u8 eq_num;
	u8 eq_rfu[2];
	u8 *eq_coef;

	u8 drc_en;
	u8 drc_type;
	u8 drc_rfu[2];
	u8 *drc_coef;
} eq_drc_cfg_t;

const u8  *dac_avol_table;
const u16 *dac_dvol_table;

AT(.text.bsp.dac.table)
const u8 dac_vol_tbl_16[16 + 1] = {
    //取值范围：(54-54) ~ (54+5),共60个值;
    //说明：值(54-54)对应音量-54dB; 54对应音量0dB;
    54-54, 54-43, 54-32, 54-26, 54-22, 54-18, 54-15, 54-12,
    54-10, 54-8,  54-6,  54-4,  54-3,  54-2,  54-1,  54,  54+1
};

AT(.text.bsp.dac.table)
const u8 dac_vol_tbl_32[32 + 1] = {
    //取值范围：(54-54) ~ (54+5),共60个值;
    //说明：值(54-54)对应音量-54dB; 54对应音量0dB;
    54-54, 54-43, 54-38, 54-35, 54-32, 54-30, 54-28, 54-26,
    54-24, 54-22, 54-21, 54-20, 54-19, 54-18, 54-17, 54-16,
    54-15, 54-14, 54-13, 54-12, 54-11, 54-10, 54-9,  54-8,
    54-7,  54-6,  54-5,  54-4,  54-3,  54-2,  54-1,  54,
    54+1,
};

AT(.text.bsp.dac.table)
const u8 dac_vol_tbl_50[50 + 1] = {
    //取值范围：(54-54) ~ (54+5),共60个值;
    //说明：值(54-54)对应音量-54dB; 54对应音量0dB;
    54-54, 54-43, 54-39, 54-38, 54-37, 54-36, 54-35, 54-34,
    54-33, 54-32, 54-31, 54-30, 54-29, 54-28, 54-27, 54-26,
    54-25, 54-24, 54-23, 54-22, 54-21, 54-20, 54-19, 54-18,
    54-17, 54-16, 54-15, 54-14, 54-13, 54-12, 54-11, 54-10,
    54-9,  54-8,  54-7,  54-6,  54-6,  54-5,  54-5,  54-4,
    54-4,  54-3,  54-3,  54-2,  54-2,  54-1,  54-1,  54,
    54,    54+1,  54+1,
};

#if DAC_DRC_EN || DAC_SOFT_EQ_EN
static eq_drc_cfg_t drc_cfg = {
    .eq_en = DAC_SOFT_EQ_EN,
    .eq_num = DAC_SOFT_EQ_NUM,
    .eq_coef = NULL,    //初始化时定义

    .drc_en = DAC_DRC_EN,
    .drc_type = 1,      //0: (L+R) / 2运算； 1： L、R独立运算
    .drc_coef = NULL,
};
#endif

#if SYS_ADJ_DIGVOL_EN || SYS_ADJ_DRC_PREV_VOL
AT(.text.bsp.dac.table)
const u16 dac_dvol_tbl_16[16 + 1] = {
    DIG_N60DB,  DIG_N43DB,  DIG_N32DB,  DIG_N26DB,  DIG_N24DB,  DIG_N22DB,  DIG_N20DB,  DIG_N18DB, DIG_N16DB,
    DIG_N14DB,  DIG_N12DB,  DIG_N10DB,  DIG_N8DB,   DIG_N6DB,   DIG_N4DB,   DIG_N2DB,   DIG_N0DB,
};

AT(.text.bsp.dac.table)
const u16 dac_dvol_tbl_32[32 + 1] = {
    DIG_N60DB,  DIG_N50DB,  DIG_N43DB,  DIG_N38DB,  DIG_N35DB,  DIG_N30DB,  DIG_N28DB,  DIG_N26DB,
    DIG_N24DB,  DIG_N22DB,  DIG_N21DB,  DIG_N20DB,  DIG_N19DB,  DIG_N18DB,  DIG_N17DB,  DIG_N16DB,
    DIG_N16DB,  DIG_N15DB,  DIG_N14DB,  DIG_N13DB,  DIG_N12DB,  DIG_N11DB,  DIG_N10DB,  DIG_N9DB,
    DIG_N8DB,   DIG_N7DB,   DIG_N6DB,   DIG_N5DB,   DIG_N4DB,   DIG_N3DB,   DIG_N2DB,   DIG_N1DB,   DIG_N0DB,
};

AT(.text.bsp.dac.table)
const u16 dac_dvol_tbl_50[50 + 1] = {
    DIG_N60DB,  DIG_N56DB,  DIG_N52DB,  DIG_N48DB,  DIG_N44DB,  DIG_N42DB,  DIG_N40DB,  DIG_N38DB,
    DIG_N37DB,  DIG_N36DB,  DIG_N35DB,  DIG_N34DB,  DIG_N33DB,  DIG_N32DB,  DIG_N31DB,  DIG_N30DB,
    DIG_N29DB,  DIG_N28DB,  DIG_N28DB,  DIG_N27DB,  DIG_N26DB,  DIG_N25DB,  DIG_N25DB,  DIG_N24DB,
    DIG_N23DB,  DIG_N22DB,  DIG_N21DB,  DIG_N20DB,  DIG_N20DB,  DIG_N19DB,  DIG_N18DB,  DIG_N18DB,
    DIG_N17DB,  DIG_N16DB,  DIG_N16DB,  DIG_N15DB,  DIG_N14DB,  DIG_N13DB,  DIG_N12DB,  DIG_N11DB,
    DIG_N10DB,  DIG_N9DB,   DIG_N8DB,   DIG_N7DB,   DIG_N6DB,   DIG_N5DB,   DIG_N4DB,   DIG_N3DB,
    DIG_N2DB,   DIG_N1DB,   DIG_N0DB,
};
#endif // SYS_ADJ_DIGVOL_EN


AT(.text.bsp.dac)
void bsp_change_volume(u8 vol)
{
#if SYS_ADJ_DRC_PREV_VOL
    drc_pre_volume_set(vol);
	return;
#endif

#if FMTX_EN
    bsp_fmtx_set_vol(vol);
#endif

#if !SYS_ADJ_DIGVOL_EN
    ///sys adjust dac analog volume
    u8 anl_vol = 0;
    if (vol <= VOL_MAX) {
        if (vol > 0) {
            anl_vol = dac_avol_table[vol] + sys_cb.anl_gain_offset;
        }
        dac_set_volume(anl_vol);
    }
#else
    ///sys adjust dac digital volume
    u16 dig_vol = 0;
    if (vol <= VOL_MAX) {
        dig_vol = dac_dvol_table[vol];
    #if AUCAR_EQ_LOUD_BASS_TREBLE_EN
        digital_vol_set_for_aucar(dig_vol);
    #else
        dac_set_dvol(dig_vol);
    #endif
        //digital_vol_set_before_eq(dig_vol,music_coef);  //只调高低音, 不支持EQ. DAC_AUCAR_EN/SYS_BASS_TREBLE_EN/SYS_ADJ_DIGVOL_EN
        //printf("dig_vol = %d\n",dig_vol);
    }
#endif
}

AT(.text.bsp.dac)
bool bsp_set_volume(u8 vol)
{
    bsp_change_volume(vol);
    if (vol == sys_cb.vol) {
        gui_box_show_vol();
        return false;
    }

    if (vol <= VOL_MAX) {
        sys_cb.vol = vol;
#if SYS_KARAOK_EN
        sys_cb.show_type = 0;
#endif
        gui_box_show_vol();
        param_sys_vol_write();
        sys_cb.cm_times = 0;
        sys_cb.cm_vol_change = 1;
    }
    return true;
}

//开机控制DAC电容放电等待时间
AT(.text.dac)
void dac_pull_down_delay(void)
{
    delay_5ms(DAC_PULL_DOWN_DELAY);
}

AT(.com_text.dac)
void dac_set_mute_callback(u8 mute_flag)
{
    if (mute_flag) {
        bsp_loudspeaker_mute();
    } else {
        if (!sys_cb.mute) {
            bsp_loudspeaker_unmute();
#if EARPHONE_DETECT_EN
            if (!dev_is_online(DEV_EARPHONE))
#endif
            {
                //DAC延时淡入，防止UNMUTE时间太短导致喇叭声音不全的问题
                dac_unmute_set_delay(LOUDSPEAKER_UNMUTE_DELAY);
            }
        }
    }
}

AT(.text.bsp.dac)
u8 bsp_volume_inc(u8 vol)
{
    vol++;
    if(vol > VOL_MAX)
        vol = VOL_MAX;
    return vol;
}

AT(.text.bsp.dac)
u8 bsp_volume_dec(u8 vol)
{
    if(vol > 0)
        vol--;
    return vol;
}

AT(.text.bsp.dac)
void dac_set_anl_offset(u8 bt_call_flag)
{
    if (bt_call_flag) {
        sys_cb.anl_gain_offset = 54 - 9 + BT_CALL_MAX_GAIN - dac_avol_table[VOL_MAX];
    } else {
        sys_cb.anl_gain_offset = 54 - 9 + DAC_MAX_GAIN - dac_avol_table[VOL_MAX];
    }
}

AT(.text.bsp.dac)
void dac_set_vol_table(u8 vol_max)
{
    if (vol_max == 16) {
        dac_avol_table = dac_vol_tbl_16;
#if SYS_ADJ_DIGVOL_EN || SYS_ADJ_DRC_PREV_VOL
        dac_dvol_table = dac_dvol_tbl_16;
#endif // SYS_ADJ_DIGVOL_EN
    } else if (vol_max <= 32) {
        dac_avol_table = dac_vol_tbl_32;
#if SYS_ADJ_DIGVOL_EN || SYS_ADJ_DRC_PREV_VOL
        dac_dvol_table = dac_dvol_tbl_32;
#endif // SYS_ADJ_DIGVOL_EN
    } else {
        dac_avol_table = dac_vol_tbl_50;
#if SYS_ADJ_DIGVOL_EN || SYS_ADJ_DRC_PREV_VOL
        dac_dvol_table = dac_dvol_tbl_50;
#endif // SYS_ADJ_DIGVOL_EN
    }
    dac_set_anl_offset(0);
}

#if SINE_TONE_EN
AT(.com_text) const char sine6[12] = {0x5C, 0xC4, 0xE7, 0xE2, 0xB4, 0x1E, 0xA8, 0x3B, 0xAC, 0x1C, 0xA2, 0xE0};  //正弦波一个周期的6个采样点 //频率16K/6 = 2.67K
//播放请调用 sine_tone_play();
#endif


AT(.text.dac)
u8 mono_dac_out_lr_sel(void)  //TWS 单声道从哪个声道输出选则
{
    return 1;  //1 DACL  //2 DACR
}


//#if AUDIO_STRETCH_EN
//void stretch_level_test(void)   //初始化需要调用bsp_stretch_init();
//{
//    static u8 level = 0;
//    static u8 type = 1;
//    stretch_voice_set_level(type,level); //type:0(高音), 1(低音)， level:0~7
//    level++;
//    if (level > 7) {
//        level = 0;
//        type = type ? 0:1;   //高低音切换测试
//    }
//}
//#endif



AT(.text.bsp.dac)
void dac_init(void)
{
    dac_set_vol_table(xcfg_cb.vol_max);
    printf("[%s] vol_max:%d, offset: %d\n", __func__, xcfg_cb.vol_max, sys_cb.anl_gain_offset);

    adpll_init(DAC_OUT_SPR);
    dac_obuf_init();
    dac_power_on();

#if (DAC_OUT_SPR == DAC_OUT_48K)
    DACDIGCON0 |= BIT(1);           //dac out sample 48K
#endif
    dac_digital_enable();

#if DAC_SOFT_EQ_EN || DAC_DRC_EN ||DAC_XDRC_EN
    #ifdef RES_BUF_DRC_ALL_EQ
    drc_cfg.eq_coef = (u8*)RES_BUF_DRC_ALL_EQ;   //默认初始化 normal.eq 资源文件
    #endif
    #ifdef RES_BUF_DRC_ALL_DRC
    drc_cfg.drc_coef = (u8*)RES_BUF_DRC_ALL_DRC;
    #endif

#if DAC_XDRC_EN
    drc_init_lp((const u32*)RES_BUF_DRC_LP_DRC);  //lp drc //offset 8 byte
    drc_init_hp((const u32*)RES_BUF_DRC_HP_DRC);  //hp drc          //offset 8 byte
    soft_eq_init_lp_hp(((const u32*)RES_BUF_DRC_LP_EQ), ((const u32*)RES_BUF_DRC_HP_EQ));  //lp & hp filter //0ffset 4 byte
#endif
    dac_drc_init(&drc_cfg);
#endif
    plugin_music_eq();

#if SYS_ADJ_DIGVOL_EN
    dac_set_volume(54);             //analog volume设置0DB
#endif // SYS_ADJ_DIGVOL_EN

#if SYS_ADJ_DRC_PREV_VOL
    dac_set_volume(54);             //analog volume设置0DB
    dac_set_dvol(0x7E00);           //digital volume设置0DB
#endif

#if DAC_DNR_EN
    dac_dnr_init(2, 0x10, 40, 0x10); //dnr, 20ms检测一次. 自动MUTE时间计算: 40*20 = 800ms  + 16(16级音量)*5 (模拟音量淡出) + 60ms(数字音量淡出) = 940ms
#endif

#if DAC_AUCAR_EN
    bsp_aucar_init();
#endif // DAC_AUCAR_EN



#if DAC_VBS_EN
    dac_vbs_init(NULL);
#endif

#if SINE_TONE_EN
    sine_tone_init((void*)sine6,sizeof(sine6),5906);
#endif
}


#if SYS_ADJ_DRC_PREV_VOL
static u16 drc_pre_vol = MAX_DIG_VAL;

void drc_pre_volume_set(u16 vol)
{
    drc_pre_vol = dac_dvol_table[vol];
    printf("drc_pre_volume_set %d_0x%X\n", vol,drc_pre_vol);
}

u16 drc_pre_volume_get(void)
{
    return drc_pre_vol;
}

//AT(.com_text.const)
//const char strx1[] = ">";

AT(.com_text.soft.de)
void drc_pre_gain_process(s32* value)
{
    s32 input = *value;
    input = (input * drc_pre_vol)>>15;     //0DB 32767 (2^15)
    *value = input;

//    static u32 ticks = 0;
//    if (tick_check_expire(ticks,1000)) {
//        ticks = tick_get();
//        printf(strx1);
//    }
}
#endif

////IIS输出时,要求数据快速输出，此函数关闭dac_fade操作。让IIS快速出数据
//AT(.com_text.dac)
//bool dac_fade_out_dis(void)
//{
//    return true;
//}

//-----FFT_TEST------//
/*

//  说明：FFT计算需要传入128个s32的点，计算出来之后有64个点也就是128个数，分别为实部1、虚部1；实部2、虚部2...实部64、虚部64.
//  也就是说计算结果的64个点可以表示  采样率/2 的频谱范围
//  1k正弦波峰值在第3个点左右
//  使用FFT最好打开120M系统时钟
//  使用时直接调用nr_rdft_forward_256（）就可以得到想要的FFT，再进行取模即可

void nr_rdft_forward_256(s32 *buf);
s32 fft_buf[256] ;//AT(.softfft.buf);
void nr_rdft_inverse_256(s32* buf);
#if 0
AT(.text.func.table)
const u8 test_data128[256] = {  //1k
    0x27, 0x40, 0x9A, 0x3F,
	0xF6, 0x3D, 0x45, 0x3B, 0x8F, 0x37, 0xE4, 0x32, 0x5C, 0x2D, 0x0D, 0x27, 0x14, 0x20, 0x8D, 0x18,
	0x9B, 0x10, 0x60, 0x08, 0x00, 0x00, 0xA0, 0xF7, 0x65, 0xEF, 0x73, 0xE7, 0xEC, 0xDF, 0xF2, 0xD8,
	0xA4, 0xD2, 0x1C, 0xCD, 0x72, 0xC8, 0xBC, 0xC4, 0x0A, 0xC2, 0x66, 0xC0, 0xDA, 0xBF, 0x67, 0xC0,
	0x09, 0xC2, 0xBC, 0xC4, 0x72, 0xC8, 0x1B, 0xCD, 0xA3, 0xD2, 0xF4, 0xD8, 0xED, 0xDF, 0x74, 0xE7,
	0x66, 0xEF, 0xA1, 0xF7, 0x00, 0x00, 0x60, 0x08, 0x9A, 0x10, 0x8C, 0x18, 0x13, 0x20, 0x0E, 0x27,
	0x5C, 0x2D, 0xE4, 0x32, 0x8E, 0x37, 0x44, 0x3B, 0xF7, 0x3D, 0x9A, 0x3F, 0x27, 0x40, 0x9A, 0x3F,
	0xF7, 0x3D, 0x44, 0x3B, 0x8E, 0x37, 0xE5, 0x32, 0x5D, 0x2D, 0x0D, 0x27, 0x13, 0x20, 0x8D, 0x18,
	0x9A, 0x10, 0x60, 0x08, 0x00, 0x00, 0xA0, 0xF7, 0x65, 0xEF, 0x74, 0xE7, 0xED, 0xDF, 0xF2, 0xD8,
	0xA4, 0xD2, 0x1B, 0xCD, 0x72, 0xC8, 0xBC, 0xC4, 0x09, 0xC2, 0x67, 0xC0, 0xD9, 0xBF, 0x67, 0xC0,
	0x0A, 0xC2, 0xBC, 0xC4, 0x71, 0xC8, 0x1B, 0xCD, 0xA4, 0xD2, 0xF3, 0xD8, 0xED, 0xDF, 0x73, 0xE7,
	0x65, 0xEF, 0xA1, 0xF7, 0x00, 0x00, 0x60, 0x08, 0x9A, 0x10, 0x8C, 0x18, 0x13, 0x20, 0x0D, 0x27,
	0x5D, 0x2D, 0xE4, 0x32, 0x8F, 0x37, 0x44, 0x3B, 0xF6, 0x3D, 0x9B, 0x3F, 0x27, 0x40, 0x9A, 0x3F,
	0xF7, 0x3D, 0x45, 0x3B, 0x8E, 0x37, 0xE5, 0x32, 0x5D, 0x2D, 0x0D, 0x27, 0x13, 0x20, 0x8D, 0x18,
	0x9A, 0x10, 0x5F, 0x08, 0x00, 0x00, 0xA1, 0xF7, 0x65, 0xEF, 0x74, 0xE7, 0xED, 0xDF, 0xF2, 0xD8,
	0xA4, 0xD2, 0x1B, 0xCD, 0x71, 0xC8, 0xBC, 0xC4, 0x09, 0xC2, 0x66, 0xC0, 0xDA, 0xBF, 0x67, 0xC0,
	0x09, 0xC2, 0xBC, 0xC4, 0x72, 0xC8, 0x1C, 0xCD, 0xA3, 0xD2, 0xF3, 0xD8
};
#endif
void max_print(u32 *num, u16 N)
{
    int i;    //控制循环
    int index = 0;    //最大值下标
    u32 max;
//    int num[N];    //用于存储数组数据

    //寻找最大值及其下标
    max = num[0];
    for(i=0; i<N; i++){
        if(max<num[i]){
            max = num[i];
            index = i;
        }
    }

    printf("max = %u\n",max);
    printf("max_i = %d\n",index);
}
void fft_test(void)
{

    u32 *uptr = (u32*)fft_buf;
    s16 *s16_ptr = (s16*)test_data128;
//            u8 *buf_ptr;
    s32 *sptr = (s32*)fft_buf;

    memset(fft_buf, 0x0, 512);  //清buff

    for (u8 j = 0; j < 128; j++)
    {
        uptr[j] = s16_ptr[j];   //填buff
    }

    nr_rdft_forward_256(sptr);  //FFT 计算
    for (u8 j = 0; j < 128; j++)
    {
        if (sptr[j] < 0) {
            sptr[j] = 0 - sptr[j];  //取模前先把负数转正
        }
    }

    for (u8 k = 0; k < 64; k++)     //取模，S64是防止数据溢出
    {
        sptr[k] = (s32)(((((s64)sptr[2*k]*(s64)sptr[2*k]) + ((s64)sptr[2*k + 1]*(s64)sptr[2*k + 1])))/100000);
    }
    max_print(uptr, 64);            //取得输出的64个点中，赋值最大的数和对应的位置
}


*/
//-----TEST_END------//

